#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <linux/types.h>
#include<stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>

#include "binder.h"

// Hello Service 命令定义
#define HELLO_SVR_CMD_SAYHELLO     1
#define HELLO_SVR_CMD_SAYHELLO_TO  2

// Food Service 命令定义
#define FOOD_SVR_CMD_ORDER_FOOD    1

int g_handle = 0;
struct binder_state *g_bs;

/**
 * 客户端调用 hello 服务
 * @param bs binder 状态
 * @param handle 服务句柄
 * @return 调用结果
 */
int sayhello(struct binder_state *bs, uint32_t handle)
{
    ATRACE_BEGIN_FUNC("sayhello");
    unsigned iodata[512/4];
    struct binder_io msg, reply;
    int ret;
    
    // 获取当前进程和线程信息
    pid_t pid = getpid();
    pid_t tid = syscall(SYS_gettid);
    
    printf("[CLIENT][PID:%d,TID:%d] Calling sayhello service\n", pid, tid);

    /* 构造binder_io */
    bio_init(&msg, iodata, sizeof(iodata), 4);
    bio_put_uint32(&msg, 0);  // strict mode header
    bio_put_string16_x(&msg, "IHelloService");

    /* 调用binder_call */
    if (binder_call(bs, &msg, &reply, handle, HELLO_SVR_CMD_SAYHELLO)) {
        printf("[CLIENT][PID:%d,TID:%d] ERROR: binder_call failed for sayhello\n", pid, tid);
        ATRACE_END_FUNC();
        return -1;
    }
    
    /* 从reply中解析结果 */
    ret = bio_get_uint32(&reply);
    printf("[CLIENT][PID:%d,TID:%d] sayhello service returned: %d\n", pid, tid, ret);
    
    binder_done(bs, &msg, &reply);
    
    ATRACE_END_FUNC();
    return ret;
}

/**
 * 客户端调用点外卖服务
 * @param bs binder 状态
 * @param handle 服务句柄
 * @param food_name 外卖名称
 * @return 订单号
 */
int order_food(struct binder_state *bs, uint32_t handle, const char *food_name)
{
    ATRACE_BEGIN_FUNC("order_food");
    unsigned iodata[512/4];
    struct binder_io msg, reply;
    int ret;
    
    // 获取当前进程和线程信息
    pid_t pid = getpid();
    pid_t tid = syscall(SYS_gettid);
    
    printf("[CLIENT][PID:%d,TID:%d] Calling order_food service for: %s\n", pid, tid, food_name);

    /* 构造binder_io */
    bio_init(&msg, iodata, sizeof(iodata), 4);
    bio_put_uint32(&msg, 0);  // strict mode header
    bio_put_string16_x(&msg, "IFoodService");
    bio_put_string16_x(&msg, food_name);  // 外卖名称参数

    /* 调用binder_call */
    if (binder_call(bs, &msg, &reply, handle, FOOD_SVR_CMD_ORDER_FOOD)) {
        printf("[CLIENT][PID:%d,TID:%d] ERROR: binder_call failed for order_food\n", pid, tid);
        ATRACE_END_FUNC();
        return -1;
    }
    
    /* 从reply中解析结果 */
    ret = bio_get_uint32(&reply);
    printf("[CLIENT][PID:%d,TID:%d] order_food service returned order_id: %d\n", pid, tid, ret);
    
    binder_done(bs, &msg, &reply);
    
    ATRACE_END_FUNC();
    return ret;
}

/**
 * 主函数
 * 连接到 binder 驱动，查找服务，调用服务
 */
int main(int argc, char **argv)
{
    ATRACE_BEGIN_FUNC("main");
    struct binder_state *bs;
    uint32_t svcmgr = BINDER_SERVICE_MANAGER;
    uint32_t handle;
    int ret;
    
    // 获取当前进程信息
    pid_t pid = getpid();
    printf("[CLIENT][PID:%d] Binder client starting...\n", pid);

    // 打开 binder 设备
    bs = binder_open("/dev/binder", 128*1024);
    if (!bs) {
        fprintf(stderr, "failed to open binder driver\n");
        ATRACE_END_FUNC();
        return -1;
    }
    printf("[CLIENT][PID:%d] Successfully opened binder driver\n", pid);

    // 获取 hello 服务
    printf("[CLIENT][PID:%d] Looking up hello service...\n", pid);
    uint32_t hello_handle = svcmgr_lookup(bs, svcmgr, "hello");
    if (!hello_handle) {
        fprintf(stderr, "failed to get hello service\n");
        ATRACE_END_FUNC();
        return -1;
    }
    printf("[CLIENT][PID:%d] Found hello service, handle=%u\n", pid, hello_handle);

    // 获取 food 服务
    printf("[CLIENT][PID:%d] Looking up food service...\n", pid);
    uint32_t food_handle = svcmgr_lookup(bs, svcmgr, "food");
    if (!food_handle) {
        fprintf(stderr, "failed to get food service\n");
        ATRACE_END_FUNC();
        return -1;
    }
    printf("[CLIENT][PID:%d] Found food service, handle=%u\n", pid, food_handle);

    // 调用 hello 服务
    printf("[CLIENT][PID:%d] Calling hello service...\n", pid);
    ret = sayhello(bs, hello_handle);
    if (ret == 0) {
        printf("[CLIENT][PID:%d] Hello service call completed successfully\n", pid);
    } else {
        printf("[CLIENT][PID:%d] Hello service call failed with ret=%d\n", pid, ret);
    }

    // 等待 500ms
    printf("[CLIENT][PID:%d] Waiting 500ms before ordering food...\n", pid);
    usleep(500 * 1000);  // 500ms

    // 调用点外卖服务（使用 food 服务句柄）
    printf("[CLIENT][PID:%d] Calling order food service...\n", pid);
    int order_id = order_food(bs, food_handle, "宫保鸡丁");
    if (order_id > 0) {
        printf("[CLIENT][PID:%d] Order food service completed successfully, order_id=%d\n", pid, order_id);
    } else {
        printf("[CLIENT][PID:%d] Order food service failed with order_id=%d\n", pid, order_id);
    }

    printf("[CLIENT][PID:%d] Binder client exiting\n", pid);
    ATRACE_END_FUNC();
    return (ret == 0 && order_id > 0) ? 0 : -1;
}